package edu.pku.sei.modeler.uml.commands.deployment;

import java.util.ArrayList;

import edu.pku.sei.modeler.model.core.MetaPackage;
import edu.pku.sei.modeler.model.structure.MetaNode;
import edu.pku.sei.modeler.model.uml.Artifacts.Artifact;
import edu.pku.sei.modeler.model.uml.Nodes.Deployment;
import edu.pku.sei.modeler.model.uml.Nodes.Node;
import edu.pku.sei.modeler.uml.commands.NestedElementDeleteCommand;

public class NestedNodeElementDeleteCommand extends NestedElementDeleteCommand {
	private Node father;
	private MetaPackage pkg;
	private ArrayList deployments = new ArrayList();
	public NestedNodeElementDeleteCommand(MetaNode node, MetaNode fatherNode,
			boolean isDeletedFromDiagram) {
		super(node, fatherNode, isDeletedFromDiagram);
		this.father = (Node) fatherNode.getModelElement();
	}
	
	@Override
	protected void deleteModelElement() {
		if (node.getModelElement() instanceof Artifact) {
			Artifact child = (Artifact) node.getModelElement();
			for (int i = 0; i < child.getSupplierDependency().size(); i++){
				Object d = child.getSupplierDependency().get(i);
				if (d instanceof Deployment) {
					deployments.add(d);
					child.getSupplierDependency().remove(d);
					father.getDeployment().remove(d);
					pkg = getMetaPackageOfNode(father);
				}
			}
			if (pkg != null){
				pkg.getOtherElements().remove(child);
			}
		}
		else if (node.getModelElement() instanceof Node) {
			Node child = (Node)node.getModelElement();
			father.getNestedNode().remove(child);
		}
	}
	@Override
	protected void undoDeleteModelElement() {
		if (node.getModelElement() instanceof Artifact) {
			Artifact child = (Artifact) node.getModelElement();
			for (Object i : deployments){
				child.getSupplierDependency().add(i);
				father.getDeployment().add(i);
			}
			if (pkg != null){
				pkg.getOtherElements().add(child);
			}
		}
		else if (node.getModelElement() instanceof Node) {
			Node child = (Node)node.getModelElement();
			father.getNestedNode().add(child);
		}
	}
	
	private MetaPackage getMetaPackageOfNode(Node node) {
		for (Object pkg : node.getModel().getPackages()) {
			if (isNodeInMetaPackage(node, (MetaPackage) pkg) != null)
				return (MetaPackage) pkg;
		}
		return null;
	}

	private MetaPackage isNodeInMetaPackage(Node node, MetaPackage pkg) {
		if (pkg.getOtherElements().contains(node))
			return pkg;
		for (Object element : pkg.getOtherElements()) {
			if (element instanceof Node && isNodeInNode(node, (Node) element)) {
				return pkg;
			}
		}
		for (Object subPkg : pkg.getSubPackages()) {
			if (isNodeInMetaPackage(node, (MetaPackage) subPkg) != null)
				return (MetaPackage) subPkg;
		}
		return null;

	}
		
	private boolean isNodeInNode(Node child, Node father) {
		if (father.getNestedNode().contains(child))
			return true;
		for (Object element : father.getNestedNode()) {
			if (isNodeInNode(child, (Node) element))
				return true;
		}
		return false;
	}

}
